#include <SGE.h>
#include <time.h>
#include <thread>
#include <list>
using namespace SGE;
#include "Bullet.h"
#include "Fighter.h"
#include "Enemy.h"


bool quit = false; //replaces hard coded false to quite game

Fighter fighter;
const int kMaxBullets = 100;
Bullet bullets[kMaxBullets];
int bulletIndex = 0;

const int kMaxEnemy = 100;
Enemy enemy[kMaxEnemy];
int enemyIndex = 0;

float spawnDelay = 0.0f;

const int kMaxExplosion = 100;
SGE_Emitter explosions[kMaxExplosion];
int explosionIndex = 0;

SGE_Sprite backGround;
SGE_Sound fireSound,explosionSound;

void UpdateGameObjects(float deltaTime)
{
	fighter.Update(deltaTime);
	for(int i = 0; i < kMaxBullets; i++)
	{
		bullets[i].Update(deltaTime);
	}

	for(int i = 0; i < kMaxEnemy; i++)
	{
		enemy[i].Update(deltaTime);
	}

	for(int i = 0; i < kMaxBullets; i++)
	{
		explosions[i].Update(deltaTime);
	}
}

void FireBullets()
{
	if(Input_IsKeyPressed(Keys::SPACE))
	{
		fireSound.Play();
		
		const int index0 = bulletIndex;//index1
		const int index1 = (bulletIndex + 1) % kMaxBullets;//index2
		const int index2 = (bulletIndex + 2) % kMaxBullets;//to prevent the last index out of bound, 
		if (!bullets[index0].IsActive() &&
			!bullets[index1].IsActive() &&
			!bullets[index2].IsActive())
		{
			SVector2 pos0 = fighter.GetPosition();
			SVector2 vel0(0.0f, -600.0f); //velocity shoots in the negative y direction because our coordinate system is top-down
			bullets[index0].Fire(pos0, vel0);

			SVector2 pos1 = fighter.GetPosition();
			SVector2 vel1(50.0f, -600.0f); //velocity shoots in the negative y direction because our coordinate system is top-down
			bullets[index1].Fire(pos1, vel1);

			SVector2 pos2 = fighter.GetPosition();
			SVector2 vel2(-50.0f, -600.0f); //velocity shoots in the negative y direction because our coordinate system is top-down
			bullets[index2].Fire(pos2, vel2);

			bulletIndex = (index2 + 1) % kMaxBullets;
		}
	}
}

void SpawnEnemies(float deltaTime)
{
	//spawn enemies every specifict time
	spawnDelay -= deltaTime;
	if(spawnDelay <= 0.0f)
	{
		//it is time to spawn!
		if(!enemy[enemyIndex].IsActive())
		{
			float randomX = rand() % IniFile_GetInt("WinWidth", 800.0f);
			float initialY = 0.0f;
			SVector2 pos(randomX, initialY);
			enemy[enemyIndex].Spawn(pos);
			enemyIndex = (enemyIndex+1) % kMaxEnemy;
			//reset delay time
			spawnDelay = RandomFloat(0.5f, 2.0f);
		}
	}
}

void CheckCollision()
{
	for(int e = 0; e < kMaxEnemy; e++)
	{
		if(enemy[e].IsActive())
		{
			for(int b = 0; b < kMaxBullets; b++)
			{
				if(bullets[b].IsActive())
				{
					SCircle eCircle = enemy[e].GetBoundingCircle();
					SCircle bCircle = bullets[b].GetBoundingCircle();
					
					//Graphics_DebugCircle(eCircle, 0xff0000);
					//Graphics_DebugCircle(bCircle, 0xff0000);
					/*float xDiff = eCircle.center.x - bCircle.center.x;
					float yDiff = eCircle.center.y - bCircle.center.y;
					float dist = sqrt(xDiff * xDiff + yDiff +yDiff);
					float radii = eCircle.radius + bCircle.radius;
					
					if(dist <= radii)
					{
						enemy[e].Kill();
						bullets[b].Kill();
						break;
					}*/

					if(Intersect(eCircle, bCircle))
					{
						enemy[e].Kill();
						bullets[b].Kill();
						
						explosionSound.Play();
						explosions[explosionIndex].SetPosition(eCircle.center);
						explosions[explosionIndex].Start(100.0f, true);
						explosionIndex = (explosionIndex+1) % kMaxExplosion;

						break;
					}
				}
			}
		}
	}
}

void SGE_Initialize()
{
	fighter.Load();
	SVector2 playerPos;
	playerPos.x = (IniFile_GetInt("WinWidth", 800)) * 0.5f;
	playerPos.y = (IniFile_GetInt("WinHeight", 600)) * 0.75f;
	fighter.SetPosition(playerPos);
	for(int i = 0; i < kMaxBullets; i++)
	{
		bullets[i].Load();
	}
	for(int i = 0; i < kMaxEnemy; i++)
	{
		enemy[i].Load();
	}
	for(int i = 0; i < kMaxExplosion; i++)
	{
		explosions[i].Load("explosion.txt");
	}
	backGround.Load("space.jpg");
	fireSound.Load("photongun1.wav");
	explosionSound.Load("explosion.wav");
}

void SGE_Terminate()
{
	fighter.Unload();
	for(int i = 0; i < kMaxBullets; i++)
	{
		bullets[i].Unload();
	}
	for(int i = 0; i < kMaxEnemy; i++)
	{
		enemy[i].Unload();
	}
	for(int i = 0; i < kMaxExplosion; i++)
	{
		explosions[i].Unload();
	}
	backGround.Unload();
	fireSound.Unload();
	explosionSound.Unload();
}

bool SGE_Update(float deltaTime)
{
	UpdateGameObjects(deltaTime);
	FireBullets();
	SpawnEnemies(deltaTime);
	CheckCollision();
	//virtual key codes: included in Input.h (accessed using Keys namespace)
	if(Input_IsKeyPressed(Keys::ESCAPE)) 
	{
		quit = true;
	}
	return quit;
}

void SGE_Render()
{
	backGround.Render();
	for(int i = 0; i < kMaxBullets; i++)
	{
		bullets[i].Render();
	}
	for(int i = 0; i < kMaxEnemy;i++)
	{
		enemy[i].Render();
	}
	for(int i = 0; i < kMaxExplosion; i++)
	{
		explosions[i].Render(true);
	}
	fighter.Render();
}